package com.ymt.bpm.service.platform.fauth.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ymt.bpm.dao.MDao;
import com.ymt.bpm.dao.Mapper;
import com.ymt.bpm.model.Const.Oplog;
import com.ymt.bpm.model.PResource;
import com.ymt.bpm.model.PRole;
import com.ymt.bpm.service.platform.fauth.FaResService;
import com.ymt.bpm.service.platform.log.OpLogService;
import com.ymt.bpm.util.AES;
import com.ymt.bpm.util.Const;
import com.ymt.bpm.util.DateUtil;
import com.ymt.bpm.util.DhxUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by Johnny on 2017/3/7.
 */
@Service
public class FaResServiceImpl implements FaResService {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private MDao mDao;

    @Autowired
    private OpLogService oplog;

    /**
     * get all admin menu without tenantId for supervisor
     * @return
     */
    @Override
    public JSONArray getSuperVisorAdminMenu() {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("purpose", PResource.PURPOSE_ADMIN);
        List<PResource> list = mDao.selectList(Mapper.PResourceMapper, "selectAllMenu", paramMap);
        JSONArray rtn = new JSONArray();
        JSONArray children = getChildrenRes(list, "ROOT-ADMIN");
        rtn.addAll(children);
        return rtn;
    }

    /**
     * get all admin menu with tenantId
     * @return
     */
    @Override
    public JSONArray getAllAdminMenu(String tenantId) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("purpose", PResource.PURPOSE_ADMIN);
        List<PResource> list = mDao.selectList(Mapper.PResourceMapper, "selectAllMenu", paramMap);
        JSONArray rtn = new JSONArray();
        String rootId = "ROOT-ADMIN";// + (tenantId!=null && StringUtils.isNumeric(tenantId) ? "-"+tenantId : "");
        JSONArray children = getChildrenRes(list, rootId);
        rtn.addAll(children);
        return rtn;
    }

    @Override
    public JSONArray getUserAdminMenu(String tenantId, String loginName) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put(Const.LOGINNAME, loginName);
        paramMap.put("purpose", PResource.PURPOSE_ADMIN);
        List<PResource> list = mDao.selectList(Mapper.PResourceMapper, "selectUserMenu", paramMap);
        JSONArray rtn = new JSONArray();
        String rootId = "ROOT-ADMIN";// + (tenantId!=null && StringUtils.isNumeric(tenantId) ? "-"+tenantId : "");
        JSONArray children = getChildrenRes(list, rootId);
        rtn.addAll(children);
        return rtn;
    }

    @Override
    public JSONObject getUserPortalMenu(String tenantId, String loginName) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put(Const.LOGINNAME, loginName);
        //paramMap.put("purpose", PResource.PURPOSE_PORTAL);    //需要检查isAdmin
        List<PResource> list = mDao.selectList(Mapper.PResourceMapper, "selectUserMenu", paramMap);
        JSONArray portalMenus = new JSONArray();
        String rootIdPortal = "ROOT-PORTAL";// + (tenantId!=null && StringUtils.isNumeric(tenantId) ? "-"+tenantId : "");
        JSONArray children = getChildrenRes(list, rootIdPortal);
        portalMenus.addAll(children);
        JSONObject rtn = new JSONObject();
        rtn.put("portalMenus", portalMenus);
        String rootId = "ROOT-ADMIN";// + (tenantId!=null && StringUtils.isNumeric(tenantId) ? "-"+tenantId : "");
        rtn.put("isAdmin", checkIsAdmin(list, rootId));
        return rtn;
    }

    /**
     *
     * @param tenantId
     * @param loginName
     * @param lang
     * @param purpose -1=all 0-admin 1-portal
     * @param timezoneOffset
     * @return
     */
    @Override
    public JSONArray tree(String tenantId, String loginName, String lang, int purpose, int timezoneOffset) {
        JSONArray arr = new JSONArray();
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        if (purpose>=0) {
            paramMap.put("purpose", purpose);
        }
        paramMap.put("reverseSort", "true");
        List<PResource> list = mDao.selectList(Mapper.PResourceMapper, "selectAllMenu", paramMap);
        if (list!=null && list.size()>0) {
            for (PResource res : list) {
                //JSONObject row = DhxUtil.toFastJsonWithDate(res, lang, timezoneOffset);
                if (!res.getIsvalid()) {
                    continue;
                }
                JSONObject row = new JSONObject();
                row.put("id", res.getResId());
                row.put("text", res.getResName());
                row.put("parentId", res.getParentId());
                row.put("resType", res.getResType());
                row.put("sort", res.getSort());
                row.put("ispreset", res.getIspreset());
                row.put("resName", res.getResName());
                row.put("resDesc", res.getResDesc());
                row.put("resUri", res.getResUri());
                row.put("iconcls", res.getIconcls());
                row.put("creator", res.getCreator());
                row.put("createTime", DateUtil.formatDate(res.getCreateTime(), DateUtil.DATEFORMATSS_ZH, timezoneOffset));
                arr.add(row);
            }
        }
        return arr;
    }

    @Override
    public int reorder(String tenantId, String loginName, String displayName, String orders) {
        JSONObject oj = JSONObject.parseObject(orders);
        int rs = 0;
        for (Map.Entry<String, Object> entry : oj.entrySet()) {
            PResource res = new PResource();
            res.setResId(entry.getKey());
            res.setSort((Integer)entry.getValue());
            rs += mDao.update(Mapper.PResourceMapper, "updateByPrimaryKeySelective", res);
        }

        //记录日志
        oplog.bizlog(tenantId, loginName, displayName, null, Oplog.OP.REORDER, Oplog.CODE.RESOURCE, null);

        return rs;
    }

    @Override
    public JSONObject save(String tenantId,
                           String loginName,
                           String displayName,
                           String lang,
                           int timezoneOffset,
                           PResource resource) {
        int rs = 0;
        JSONObject rtn = new JSONObject();
        if (resource.getResId()==null || resource.getResId().length()==0) {
            String resId = "RES-"+ UUID.randomUUID().toString();
            if (tenantId!=null && StringUtils.isNumeric(tenantId)) {
                resource.setTenantId(Integer.parseInt(tenantId));
            }
            resource.setResId(resId);
            resource.setCreatorId(loginName);
            resource.setCreator(displayName);
            resource.setCreateTime(DateUtil.getGMTDate());
            resource.setIspreset(false);
            rs = mDao.insert(Mapper.PResourceMapper, "insertSelective", resource);
            JSONObject res = DhxUtil.toFastJsonWithDate(resource, lang, timezoneOffset);
            res.put("id", resId);
            res.put("text", resource.getResName());
            rtn.put("res", res);

            //记录日志
            oplog.bizlog(tenantId, loginName, displayName, null, Oplog.OP.CREATE, Oplog.CODE.RESOURCE, resource.getResName());
        } else {
            resource.setUpdateTime(DateUtil.getGMTDate());
            resource.setUpdatorId(loginName);
            resource.setUpdator(displayName);
            rs = mDao.update(Mapper.PResourceMapper, "updateByPrimaryKeySelective", resource);
            resource = mDao.selectOne(Mapper.PResourceMapper, "selectByPrimaryKey", resource.getResId());
            JSONObject res = DhxUtil.toFastJsonWithDate(resource, lang, timezoneOffset);
            res.put("id", resource.getResId());
            res.put("text", resource.getResName());
            rtn.put("res", res);

            //记录日志
            oplog.bizlog(tenantId, loginName, displayName, null, Oplog.OP.DELETE, Oplog.CODE.RESOURCE, resource.getResName());
        }
        rtn.put("result", rs);
        return rtn;
    }

    @Override
    public JSONObject delete(String tenantId, String loginName, String displayName, String resId) {
        JSONObject rtn = new JSONObject();
        int rs = 0;
        PResource resource = mDao.selectOne(Mapper.PResourceMapper, "selectByPrimaryKey", resId);
        if (resource.getIspreset()) {
            rtn.put("msg","ispreset");
        }
        //check reference before delete
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("resId", resId);
        List<PRole> refRoles = mDao.selectList(Mapper.PRoleMapper, "selectResRefRoles", paramMap);
        if (refRoles!=null && refRoles.size()>0) {
            List<String> names = new ArrayList<String>();
            for (PRole role : refRoles) {
                names.add(role.getRoleName());
            }
            rtn.put("refRoles", StringUtils.join(names));
            return rtn;
        }
        rs = mDao.delete(Mapper.PResourceMapper, "deleteByPrimaryKey", resId);
        rtn.put("result", rs);

        //记录日志
        oplog.bizlog(tenantId, loginName, displayName, null, Oplog.OP.DELETE, Oplog.CODE.RESOURCE, resource.getResName());

        return rtn;
    }

    @Override
    public String checkName(String tenantId, String resName, String resId, String parentId, int purpose) {
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put(Const.TENANT_ID, tenantId);
        paramMap.put("resName", resName);
        paramMap.put("resId", resId);
        paramMap.put("parentId", parentId);
        paramMap.put("purpose", purpose);
        int count = mDao.selectOne(Mapper.PResourceMapper, "checkName", paramMap);
        return Boolean.toString(count==0);
    }

    private JSONArray getChildrenRes(List<PResource> list, String rootId) {
        JSONArray children = new JSONArray();
        if (list!=null && list.size()>0) {
            for (int i=0; i<list.size(); i++) {
                if (rootId.equalsIgnoreCase(list.get(i).getParentId())) {
                    JSONObject child = new JSONObject();
                    child.put("id", list.get(i).getResId());
                    child.put("name", list.get(i).getResName());
                    child.put("icon", list.get(i).getIconcls());
                    child.put("resType", list.get(i).getResType());
                    //判断bdm类型
                    if ("bdm".equalsIgnoreCase(list.get(i).getResType())) {
                        JSONObject uriJo = JSONObject.parseObject(list.get(i).getResUri());
                        uriJo.put("bdmIdEnc", AES.encrypt(uriJo.getString("bdmId")));
                        child.put("resUri", uriJo);
                    } else {
                        child.put("resUri", list.get(i).getResUri());
                    }
                    JSONArray subchildren = getChildrenRes(list, list.get(i).getResId());
                    if (subchildren.size()>0) {
                        child.put("children", subchildren);
                    }
                    children.add(child);
                }
            }
        }
        //sort children
        return children;
    }

    private boolean checkIsAdmin(List<PResource> list, String rootId) {
        if (list!=null && list.size()>0) {
            for (int i=0; i<list.size(); i++) {
                if (rootId.equalsIgnoreCase(list.get(i).getParentId())) {
                    return true;
                }
            }
        }
        return false;
    }
}
